/*
 * Copyright (c) 2006-2021, Halo team
 *
 * SPDX-License-Identifier: GPLv3
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-09-11     Eywen        the first version
 */

#include "hard_task.h"
#include "common.h"

static bool hard_task_init(hard_task_t *task, const char *timer_name, uint32_t freq);
static bool hard_task_start(hard_task_t *task, uint32_t freq);;
static bool hard_task_stop(hard_task_t *task);
static bool hard_task_set_run(hard_task_t *task, hard_task_run_schdule_cb cb);

const static hard_task_ops_t s_hard_task_ops =
{
    .init = hard_task_init,
    .start = hard_task_start,
    .stop = hard_task_stop,
    .set_run = hard_task_set_run,
};


/* freq： 定时器计数频率 */
bool hard_task_init(hard_task_t *task, const char *timer_name, uint32_t freq)
{
    ASSERT_NULL(task);
    ASSERT_NULL(timer_name);

    task->freq = freq;

#if defined RT_USING_HWTIMER
    /* 查找定时器设备 */
    task->hard_timer = rt_device_find(timer_name);
    if(task->hard_timer == RT_NULL){
        debug_faltal("%s not find", timer_name);
        return false;
    }
    /* 以读写方式打开设备 */
    if(rt_device_open(task->hard_timer, RT_DEVICE_OFLAG_RDWR) != RT_EOK){
        debug_faltal("%s open fail", timer_name);
        return false;
    }
    /* 设置超时回调函数 */
    //rt_device_set_rx_indicate(task->hard_timer, hard_task_run_schdule);

    /* 设置计数频率(默认1Mhz或支持的最小计数频率) */
    if(rt_device_control(task->hard_timer, HWTIMER_CTRL_FREQ_SET, &freq)
            != RT_EOK){
        debug_faltal("hwtimer_sample %s freq set fail", timer_name);
    }

    rt_hwtimer_mode_t mode;
    mode = HWTIMER_MODE_PERIOD;
    /* 设置模式为周期性定时器 */
    if(rt_device_control(task->hard_timer, HWTIMER_CTRL_MODE_SET, &mode)
            != RT_EOK){
        debug_faltal("hwtimer_sample %s mode set fail", timer_name);
    }
#else
#error "code unport"
#endif
    return true;
}

/* freq： 任务调度频率 */
bool hard_task_start(hard_task_t *task, uint32_t freq)
{
    ASSERT_NULL(task);
#if defined RT_USING_HWTIMER
    rt_hwtimerval_t timeout_s;

    /* 设置定时器超时值为5s并启动定时器 */
    timeout_s.sec = 1 / freq; /* 秒 */
    timeout_s.usec = 1000000 / freq; /* 20微秒,50K */
    if (rt_device_write(task->hard_timer, 0, &timeout_s, sizeof(timeout_s))
            != sizeof(timeout_s)){
        debug_faltal("set timeout value failed\n");
        return false;
    }
#endif
    return true;
}

bool hard_task_stop(hard_task_t *task)
{
    ASSERT_NULL(task);
#if defined RT_USING_HWTIMER
    if(rt_device_close(task->hard_timer) != RT_EOK){
        return false;
    }
#else
#error "code unport"
#endif
    return true;
}

bool hard_task_set_run(hard_task_t *task, hard_task_run_schdule_cb cb)
{
    ASSERT_NULL(task);
    ASSERT_NULL(cb);
#if defined RT_USING_HWTIMER
    /* 设置超时回调函数 */
    if(RT_EOK == rt_device_set_rx_indicate(task->hard_timer, cb)){
        return true;
    }
#else
#error "code unport"
#endif
    return false;
}

bool hard_task_register(hard_task_t *task)
{
    ASSERT_NULL(task);

    task->ops = &(s_hard_task_ops);

    return true;
}

hard_task_t *hard_task_creater(void)
{
    hard_task_t *task;

    task = MEM_MALLOC(sizeof (hard_task_t));

    if(NULL == task){
        debug_error("Insufficient system memory");
        goto err;
    }

    MEM_MEMSET(task, 0, sizeof (hard_task_t));

    if(false == hard_task_register(task)){
        debug_error("hard task register fail");
        goto err;
    }

    debug_info("hard task create success");
    return task;

err:
    if(NULL != task){
        MEM_FREE(task);
    }

    return NULL;
}
